package com.jiangyg.mall.product.controller;

import com.alibaba.fastjson.JSON;
import com.jiangyg.mall.core.support.cache.CacheAdapter;
import com.jiangyg.mall.core.support.restful.Result;
import com.jiangyg.mall.core.utils.JsonUtils;
import com.jiangyg.mall.core.utils.tree.Tree;
import com.jiangyg.mall.product.dto.CategoryDTO;
import com.jiangyg.mall.product.service.CategoryService;
import com.jiangyg.mall.product.vo.CategoryVO;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 类描述：商品三级分类控制器
 *
 * @author jiangyg
 * @version email@jiangyg.com
 * @date 2021-10-30 07:38:49
 */
@RestController
@RequestMapping("/product/category")
public class CategoryController {

    /**
     * 缓存适配器
     */
    private final CacheAdapter cacheAdapter;

    /**
     * redission
     */
    private final RedissonClient redissonClient;

    /**
     * 商品三级分类接口
     */
    private final CategoryService categoryService;

    /**
     * 缓存Key
     */
    private final static String CATEGORY_TREE_CACHEKEY = "product:category:tree";

    @Autowired
    public CategoryController(CategoryService categoryService,
                              CacheAdapter cacheAdapter,
                              RedissonClient redissonClient) {
        this.categoryService = categoryService;
        this.cacheAdapter = cacheAdapter;
        this.redissonClient = redissonClient;
    }

    /**
     * 功能描述：商城的分类树查询
     *
     * @param request 请求
     * @return 结果
     */
    @ResponseBody
    @GetMapping("/tree")
    public String tree(HttpServletRequest request) throws Exception {
        // 先从缓存获取
        String cacheValue = cacheAdapter.get(CATEGORY_TREE_CACHEKEY);
        if (cacheValue != null) {
            return cacheValue;
        }
        // 获取分布式锁
        final RLock lock = redissonClient.getLock("lock:product:category:tree");
        try {
            // 尝试加锁，最多等待5秒，上锁以后5秒自动解锁
            final boolean sucess = lock.tryLock(1115, 1115, TimeUnit.SECONDS);
            if (!sucess) {
                return JSON.toJSONString(new ArrayList<String>());
            }
            // 再次从缓存获取，如果有值则直接返回
            cacheValue = cacheAdapter.get(CATEGORY_TREE_CACHEKEY);
            if (cacheValue != null) {
                return cacheValue;
            }
            // 放入缓存
            cacheValue = JsonUtils.toJSONString(Result.ok(categoryService.tree()));
            cacheAdapter.put(CATEGORY_TREE_CACHEKEY, cacheValue);
            return cacheValue;
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
    }

    /**
     * 功能描述：刷新商城的分类树缓存
     *
     * @param request 请求
     * @return 结果
     */
    @ResponseBody
    @PostMapping("/tree-refresh")
    public Result<Object> treeRefresh(HttpServletRequest request) throws Exception {
        final String cacheValue = JsonUtils.toJSONString(Result.ok(categoryService.tree()));
        cacheAdapter.put(CATEGORY_TREE_CACHEKEY, cacheValue);
        return Result.ok();
    }

    /**
     * 功能描述：获取目录树形结构
     *
     * @param request 请求
     * @return 目录树形结构
     */
    @ResponseBody
    @PostMapping("/mtree")
    public Result<List<Tree>> mtree(HttpServletRequest request) throws Exception {
        return Result.ok(categoryService.mtree());
    }

    /**
     * 功能描述：保存或者修改商品三级分类
     *
     * @param request 请求
     * @param dto     商品三级分类
     * @return 结果
     */
    @ResponseBody
    @PostMapping("/save")
    public Result<Object> save(HttpServletRequest request, @RequestBody @Validated CategoryDTO dto) throws Exception {
        return Result.saveOrUpdate(categoryService.saveOrUpdate(dto));
    }

    /**
     * 功能描述：根据ID获取商品三级分类
     *
     * @param request    请求
     * @param categoryId 商品三级分类ID
     * @return 结果
     */
    @ResponseBody
    @PostMapping("/info")
    public Result<CategoryVO> selectById(HttpServletRequest request, @RequestParam(name = "categoryId") Long categoryId) throws Exception {
        return Result.ok(categoryService.selectById(categoryId));
    }

    /**
     * 功能描述：删除商品三级分类
     *
     * @param request     请求
     * @param categoryIds 批量删除的商品三级分类ID
     * @return 结果
     */
    @ResponseBody
    @PostMapping("/delete")
    public Result<Object> delete(HttpServletRequest request, @RequestBody List<Long> categoryIds) {
        return Result.delete(categoryService.delete(categoryIds));
    }

}
